import { emptyNode } from "../constant";
import { HTML_TAG_STATUS } from "../constant";

export default class HNode {

    /**
     * 创建表示HTML节点的内存对象
     * @param {String} tag html标签的名称 （举例：div，a, h1, h2）
     * @param {Number} type html标签的类型 (举例：Node HTML节点, Comment HTML注释, Text HTML中的文本内容)
     * @param {String} status html标签的状态，是开口标签<div>，闭口标签</div>，还是独立闭合标签 <br />
     * @param {Array<{key:String, value:String}>} attrsList html标签的属性数组
     * @param {Number} start 节点对应的字符串开始的位置
     * @param {String} textContent 为 Text 节点时， 节点的文本值
     */
    constructor (tag,
                 type,
                 status,
                 attrsList,
                 start,
                 textContent) {
        this.tag = tag;
        this.type = type;
        this.status = status;
        this.attrsList = attrsList ? attrsList.slice(0) : [];
        this.start = start;
        this.parent = emptyNode;
        this.children = new Array();
        this.textContent = textContent;
    }

    /**
     * 深拷贝克隆
     *
     * 克隆hNode对象
     * 进行属性，父子关系的克隆
     * 父子节点也会一起被克隆，都不是原来引用所指向的实体，而是新的实体
     * @param {HNode} hNode
     */
    static clonedDeepHNode (hNode) {
        // 如果是空节点，则直接返回
        if (hNode === emptyNode) {
            return emptyNode;
        }
        // 类型检查
        if (!(hNode instanceof HNode)) {
            return undefined;
        }
        // 进行属性值的拷贝
        const cloneNode = new HNode(
            hNode.tag,
            hNode.type,
            hNode.status,
            hNode.attrsList,
            hNode.start);
        // 进行父子关系的拷贝
        cloneNode.parent = HNode.clonedDeepHNode(hNode.parent);
        // 进行孩子节点的深拷贝
        for (let i=0; i<hNode.children.length; i++) {
            const cloneChild = HNode.clonedDeepHNode(hNode.children[i]);
            cloneNode.children.push(cloneChild);
        }
        // 返回克隆节点
        return cloneNode;
    }

    /**
     * 浅拷贝克隆
     *
     * 克隆 hNode
     * 进行属性，父子关系的克隆
     * 属性会新申请内存进行深克隆，
     * 但父子关系的引用依然指向原来的节点
     * @param {HNode} hNode
     */
    static cloneShallowHNode (hNode) {
        // 如果是空节点，则直接返回
        if (hNode === emptyNode) {
            return emptyNode;
        }
        // 类型检查
        if (!(hNode instanceof HNode)) {
            return undefined;
        }
        // 进行属性值得拷贝
        const cloneNode = new HNode(
            hNode.tag,
            hNode.type,
            hNode.status,
            hNode.attrsList,
            hNode.start);
        // 进行双亲节点的浅拷贝
        cloneNode.parent = hNode.parent;
        // 进行孩子节点的浅拷贝
        for (let i=0; i<hNode.children.length; i++) {
            const childRef = hNode.children[i];
            cloneNode.children.push(childRef);
        }
        // 返回克隆节点
        return cloneNode;
    }

}
